package com.dituhui.tool.io;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.dituhui.tool.elastic.ElasticParameter;
import com.dituhui.tool.elastic.ElasticSearchUtil;

/**
 * ES工具
 * 
 * @author liweigu
 * 
 */
public class ESTool {
	/***
	 * 设置 执行检索的类别 ，可选值集为 0、1、2、3、4、5.不设置的话，默认为1<br />
	 * 0 - DFS_QUERY_THEN_FETCH <br />
	 * 查询是针对所有的块执行的，但返回的是足够的信息，而不是文档内容（Document）。<br />
	 * 这对于有许多块的index来说是很便利的（返回结果不会有重复的，因为块被分组了）;<br />
	 * 1 - QUERY_THEN_FETCH <br/>
	 * 最原始（也可能是最快的）实现就是简单的在所有相关的shard上执行检索并返回结果。<br />
	 * 2 - DFS_QUERY_AND_FETCH <br />
	 * 与QUERY_THEN_FETCH相同，预期一个初始的散射相伴用来为更准确的score计算分配了的term频率。<br />
	 * 3 - QUERY_AND_FETCH <br />
	 * 与QUERY_AND_FETCH相同，预期一个初始的散射相伴用来为更准确的score计算分配了的term频率。<br />
	 * 4 - SCAN <br />
	 * 在执行了没有进行任何排序的检索时执行浏览。此时将会自动的开始滚动结果集。<br />
	 * 5 - COUNT <br />
	 * 只计算结果的数量，也会执行facet。
	 */
	// 最原始（也可能是最快的）实现就是简单的在所有相关的shard上执行检索并返回结果。
	private static String QUERY_THEN_FETCH = "1";
	private static String IntPrefix = "int_";
	private static String DoublePrefix = "double_";

	/***
	 * 数据更新
	 * 
	 * @param index 索引名称
	 * @param paramsJObj json对象
	 * @param host ES服务地址
	 * @return 更新结果
	 */
	public static boolean update(String index, String id, List<String> fieldNames, List<String> fieldValues, String host) {
		ElasticSearchUtil elasticsearchUtil = new ElasticSearchUtil();
		return elasticsearchUtil.update(index, id, fieldNames, fieldValues, host);
	}

	/**
	 * 删除索引
	 * 
	 * @param index 索引名，多个索引之间使用逗号隔开
	 * @param esHost 服务地址
	 */
	public static void deleteIndex(String index, String esHost) {
		ElasticSearchUtil elasticsearchUtil = new ElasticSearchUtil();
		elasticsearchUtil.deleteIndex(index, esHost);
	}

	/**
	 * 查询
	 * 
	 * @param index 索引，多个索引之间使用逗号隔开
	 * @param queryColumnNames 查询字段名数组
	 * @param queryColumnValues 查询字段值数组
	 * @param esHost 服务地址
	 * @return 列表
	 */
	public static List<String> query(String index, String[] queryColumnNames, String[] queryColumnValues, String esHost) {
		int size = 9999;
		return query(index, queryColumnNames, queryColumnValues, size, esHost);
	}

	/**
	 * 查询
	 * 
	 * @param index 索引
	 * @param queryColumnNames 查询字段名数组
	 * @param queryColumnValues 查询字段值数组
	 * @param size 返回个数
	 * @param esHost 服务地址
	 * @return 列表
	 */
	public static List<String> query(String index, String[] queryColumnNames, String[] queryColumnValues, int size, String esHost) {
		String routing = null;
		return query(index, routing, queryColumnNames, queryColumnValues, size, esHost);
	}

	/**
	 * 查询
	 * 
	 * @param index 索引
	 * @param routing ES routing，如果值是null，ES会默认使用id字段。
	 * @param queryColumnNames 查询字段名数组
	 * @param queryColumnValues 查询字段值数组
	 * @param size 返回个数
	 * @param esHost 服务地址
	 * @return 列表
	 */
	public static List<String> query(String index, String routing, String[] queryColumnNames, String[] queryColumnValues, int size, String esHost) {
		String[] returnFields = null;
		return query(index, routing, queryColumnNames, queryColumnValues, returnFields, size, esHost);
	}

	/**
	 * 查询
	 * 
	 * @param index 索引
	 * @param routing ES routing，如果值是null，ES会默认使用id字段。
	 * @param queryColumnNames 查询字段名数组
	 * @param queryColumnValues 查询字段值数组
	 * @param returnFields 查询返回字段数组
	 * @param size 返回个数
	 * @param esHost 服务地址
	 * @return 列表
	 */
	public static List<String> query(String index, String routing, String[] queryColumnNames, String[] queryColumnValues, String[] returnFields, int size,
			String esHost) {
		String[] orderFields = null;
		return query(index, routing, queryColumnNames, queryColumnValues, returnFields, orderFields, size, esHost);
	}

	/**
	 * 查询
	 * 
	 * @param index 索引
	 * @param routing ES routing，如果值是null，ES会默认使用id字段。
	 * @param queryColumnNames 查询字段名数组
	 * @param queryColumnValues 查询字段值数组
	 * @param returnFields 查询返回字段数组
	 * @param orderFields 排序字段
	 * @param size 返回个数
	 * @param esHost 服务地址
	 * @return 列表
	 */
	public static List<String> query(String index, String routing, String[] queryColumnNames, String[] queryColumnValues, String[] returnFields,
			String[] orderFields, int size, String esHost) {
		ElasticSearchUtil elasticsearchUtil = new ElasticSearchUtil();
		elasticsearchUtil.setIndex(index);
		elasticsearchUtil.setType(QUERY_THEN_FETCH);

		ElasticParameter queryBean = new ElasticParameter();
		// 返回记录数。默认是10。
		queryBean.setSize("" + size);
		queryBean.setIndex(index);
		queryBean.setSearchtype(QUERY_THEN_FETCH);
		if (queryColumnNames == null || queryColumnValues == null) {
			queryColumnNames = new String[] { "_type" };
			queryColumnValues = new String[] { QUERY_THEN_FETCH };
		}
		Map<String, Object> map = new HashMap<String, Object>();
		int i = 0;
		for (String queryColumnName : queryColumnNames) {
			map.put(queryColumnName, queryColumnValues[i++]);
		}
		queryBean.setTerm(map);
		queryBean.setReturnFields(returnFields);
		queryBean.setOrderFields(orderFields);
		List<String> list = elasticsearchUtil.read(queryBean, routing, esHost);
		return list;
	}

	/**
	 * 查询
	 * 
	 * @param index 索引
	 * @param queryColumnNames 查询字段名数组
	 * @param queryColumnValues 查询字段值数组
	 * @param esHost 服务地址
	 * @return 列表
	 */
	public static List<Map<String, Object>> queryToMapList(String index, String[] queryColumnNames, String[] queryColumnValues, String esHost) {
		String routing = null;
		return queryToMapList(index, routing, queryColumnNames, queryColumnValues, esHost);
	}

	/**
	 * 查询
	 * 
	 * @param index 索引
	 * @param routing ES routing，如果值是null，ES会默认使用id字段。
	 * @param queryColumnNames 查询字段名数组
	 * @param queryColumnValues 查询字段值数组
	 * @param esHost 服务地址
	 * @return 列表
	 */
	public static List<Map<String, Object>> queryToMapList(String index, String routing, String[] queryColumnNames, String[] queryColumnValues, String esHost) {
		int size = 9999;
		return queryToMapList(index, routing, queryColumnNames, queryColumnValues, size, esHost);
	}

	/**
	 * 查询
	 * 
	 * @param index 索引
	 * @param routing ES routing，如果值是null，ES会默认使用id字段。
	 * @param queryColumnNames 查询字段名数组
	 * @param queryColumnValues 查询字段值数组
	 * @param esHost 服务地址
	 * @return 列表
	 */
	public static List<Map<String, Object>> queryToMapList(String index, String routing, String[] queryColumnNames, String[] queryColumnValues, int size,
			String esHost) {
		ElasticSearchUtil elasticsearchUtil = new ElasticSearchUtil();
		elasticsearchUtil.setIndex(index);
		elasticsearchUtil.setType(QUERY_THEN_FETCH);

		ElasticParameter queryBean = new ElasticParameter();
		// 返回记录数。默认是10。
		queryBean.setSize("" + size);
		queryBean.setIndex(index);
		queryBean.setSearchtype(QUERY_THEN_FETCH);
		Map<String, Object> map = new HashMap<String, Object>();
		int i = 0;
		for (String queryColumnName : queryColumnNames) {
			map.put(queryColumnName, queryColumnValues[i++]);
		}
		queryBean.setTerm(map);
		List<Map<String, Object>> list = elasticsearchUtil.readToMapList(queryBean, routing, esHost);
		return list;
	}

	/**
	 * 写入
	 * 
	 * @param index 索引
	 * @param columnNames 字段名数组
	 * @param columnValues 字段值数组
	 * @param esHost 服务地址
	 * @return 写入结果
	 */
	public static String write(String index, String[] columnNames, String[] columnValues, String esHost) {
		String routing = null;
		return write(index, routing, columnNames, columnValues, esHost);
	}

	/**
	 * 写入
	 * 
	 * @param index 索引
	 * @param routing ES routing，如果值是null，ES会默认使用id字段。
	 * @param columnNames 字段名数组。int_开头的表示整型数字；double_开头的表示浮点数字，会设置字段类型，字段名会去前缀后保存。
	 * @param columnValues 字段值数组
	 * @param esHost 服务地址
	 * @return 写入结果
	 */
	public static String write(String index, String routing, String[] columnNames, String[] columnValues, String esHost) {
		ElasticSearchUtil elasticsearchUtil = new ElasticSearchUtil();

		elasticsearchUtil.setIndex(index);
		elasticsearchUtil.setType(QUERY_THEN_FETCH);

		Map<String, Object> map = new HashMap<String, Object>();
		int i = 0;
		for (String columnName : columnNames) {
			// System.out.println(columnValues[i]);
			if (columnName.startsWith(IntPrefix)) {
				columnName = columnName.substring(IntPrefix.length());
				// System.out.println("(int)version=" + columnValues[i]);
				map.put(columnName, Integer.parseInt(columnValues[i]));
				i++;
			} else if (columnName.startsWith(DoublePrefix)) {
				columnName = columnName.substring(DoublePrefix.length());
				map.put(columnName, Double.parseDouble(columnValues[i]));
				i++;
			} else {
				// System.out.println(columnName + "=" + columnValues[i]);
				map.put(columnName, columnValues[i]);
				i++;
			}
		}
		List<Map<String, Object>> datas = new ArrayList<Map<String, Object>>();
		datas.add(map);
		String result = elasticsearchUtil.write(datas, routing, esHost);
		return result;
	}
}
